/**
 * Copyright (c) 2006-2015, JGraph Ltd
 * Copyright (c) 2006-2015, Gaudenz Alder
 */
var mxClipboard =
{
    /**
     * Class: mxClipboard
     *
     * Singleton that implements a clipboard for graph cells.
     *
     * Example:
     *
     * (code)
     * mxClipboard.copy(graph);
     * mxClipboard.paste(graph2);
     * (end)
     *
     * This copies the selection cells from the graph to the clipboard and
     * pastes them into graph2.
     *
     * For fine-grained control of the clipboard data the <mxGraph.canExportCell>
     * and <mxGraph.canImportCell> functions can be overridden.
     *
     * To restore previous parents for pasted cells, the implementation for
     * <copy> and <paste> can be changed as follows.
     *
     * (code)
     * mxClipboard.copy = function(graph, cells)
     * {
     *   cells = cells || graph.getSelectionCells();
     *   var result = graph.getExportableCells(cells);
     *
     *   mxClipboard.parents = new Object();
     *
     *   for (var i = 0; i < result.length; i++)
     *   {
     *     mxClipboard.parents[i] = graph.model.getParent(cells[i]);
     *   }
     *
     *   mxClipboard.insertCount = 1;
     *   mxClipboard.setCells(graph.cloneCells(result));
     *
     *   return result;
     * };
     *
     * mxClipboard.paste = function(graph)
     * {
     *   if (!mxClipboard.isEmpty())
     *   {
     *     var cells = graph.getImportableCells(mxClipboard.getCells());
     *     var delta = mxClipboard.insertCount * mxClipboard.STEPSIZE;
     *     var parent = graph.getDefaultParent();
     *
     *     graph.model.beginUpdate();
     *     try
     *     {
     *       for (var i = 0; i < cells.length; i++)
     *       {
     *         var tmp = (mxClipboard.parents != null && graph.model.contains(mxClipboard.parents[i])) ?
     *              mxClipboard.parents[i] : parent;
     *         cells[i] = graph.importCells([cells[i]], delta, delta, tmp)[0];
     *       }
     *     }
     *     finally
     *     {
     *       graph.model.endUpdate();
     *     }
     *
     *     // Increments the counter and selects the inserted cells
     *     mxClipboard.insertCount++;
     *     graph.setSelectionCells(cells);
     *   }
     * };
     * (end)
     *
     * Variable: STEPSIZE
     *
     * Defines the step size to offset the cells after each paste operation.
     * Default is 10.
     */
    STEPSIZE: 10,

    /**
     * Variable: insertCount
     *
     * Counts the number of times the clipboard data has been inserted.
     */
    insertCount: 1,

    /**
     * Variable: cells
     *
     * Holds the array of <mxCells> currently in the clipboard.
     */
    cells: null,

    /**
     * Function: setCells
     *
     * Sets the cells in the clipboard. Fires a <mxEvent.CHANGE> event.
     */
    setCells: function (cells) {
        mxClipboard.cells = cells;
    },

    /**
     * Function: getCells
     *
     * Returns  the cells in the clipboard.
     */
    getCells: function () {
        return mxClipboard.cells;
    },

    /**
     * Function: isEmpty
     *
     * Returns true if the clipboard currently has not data stored.
     */
    isEmpty: function () {
        return mxClipboard.getCells() == null;
    },

    /**
     * Function: cut
     *
     * Cuts the given array of <mxCells> from the specified graph.
     * If cells is null then the selection cells of the graph will
     * be used. Returns the cells that have been cut from the graph.
     *
     * Parameters:
     *
     * graph - <mxGraph> that contains the cells to be cut.
     * cells - Optional array of <mxCells> to be cut.
     */
    cut: function (graph, cells) {
        cells = mxClipboard.copy(graph, cells);
        mxClipboard.insertCount = 0;
        mxClipboard.removeCells(graph, cells);

        return cells;
    },

    /**
     * Function: removeCells
     *
     * Hook to remove the given cells from the given graph after
     * a cut operation.
     *
     * Parameters:
     *
     * graph - <mxGraph> that contains the cells to be cut.
     * cells - Array of <mxCells> to be cut.
     */
    removeCells: function (graph, cells) {
        graph.removeCells(cells);
    },

    /**
     * Function: copy
     *
     * Copies the given array of <mxCells> from the specified
     * graph to <cells>. Returns the original array of cells that has
     * been cloned. Descendants of cells in the array are ignored.
     *
     * Parameters:
     *
     * graph - <mxGraph> that contains the cells to be copied.
     * cells - Optional array of <mxCells> to be copied.
     */
    copy: function (graph, cells) {
        cells = cells || graph.getSelectionCells();
        var result = graph.getExportableCells(graph.model.getTopmostCells(cells));
        mxClipboard.insertCount = 1;
        mxClipboard.setCells(graph.cloneCells(result));

        return result;
    },

    /**
     * Function: paste
     *
     * Pastes the <cells> into the specified graph restoring
     * the relation to <parents>, if possible. If the parents
     * are no longer in the graph or invisible then the
     * cells are added to the graph's default or into the
     * swimlane under the cell's new location if one exists.
     * The cells are added to the graph using <mxGraph.importCells>
     * and returned.
     *
     * Parameters:
     *
     * graph - <mxGraph> to paste the <cells> into.
     */
    paste: function (graph) {
        var cells = null;

        if (!mxClipboard.isEmpty()) {
            cells = graph.getImportableCells(mxClipboard.getCells());
            var delta = mxClipboard.insertCount * mxClipboard.STEPSIZE;
            var parent = graph.getDefaultParent();
            cells = graph.importCells(cells, delta, delta, parent);

            // Increments the counter and selects the inserted cells
            mxClipboard.insertCount++;
            graph.setSelectionCells(cells);
        }

        return cells;
    }
};